#pragma  once
#include <iostream>
#include "LOG.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <cstdlib>
#include <cstring>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8081
#define BACKLOG 5
class TcpServer{
    private:
        int listen_sock;
        int port;
        static TcpServer* tcpserver;
    private:
        TcpServer(int _port = PORT):listen_sock(),port(_port){ }
        ~TcpServer(){}
    public:

        static TcpServer* GetInstance(int _port = PORT){
            static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
            if(tcpserver == nullptr){
                pthread_mutex_lock(&lock);
                if(tcpserver == nullptr){
                    tcpserver = new TcpServer(_port);
                    tcpserver->InitTcpServer();
                }
                pthread_mutex_unlock(&lock);
            }
            return tcpserver;
        }

        void InitTcpServer(){
            CreateSock();
            BindSock();
            ListenSock();
        }

        void CreateSock(){
            listen_sock = socket(AF_INET,SOCK_STREAM,0);
            if(listen_sock < 0){
                LOG(INFO,"Create Sock Unsucess!");
                exit(1);
            }
            int opt = 1;
            setsockopt(listen_sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
            LOG(INFO,"Create Sock Sucess!");
        }
        void BindSock(){
            struct sockaddr_in local;
            memset(&local,0,sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(port);
            local.sin_addr.s_addr = INADDR_ANY;  //云服务器不可以直接绑定ip
            if(bind(listen_sock,(struct sockaddr*)&local,sizeof(local))<0){
                LOG(INFO,"Bind Sock Unsucess!");
                exit(2);
            }
            LOG(INFO,"Bind Sock Sucess!");
        }

        void ListenSock(){
            if(listen(listen_sock,BACKLOG)<0){
                LOG(INFO,"Listen Sock Unsucess!");
                exit(3);
            }
            LOG(INFO,"Listen Sock Sucess!");
        }

        int GetListenSock(){
            return listen_sock;
        }
        
};

TcpServer*  TcpServer::tcpserver = nullptr;
